package com.uinnova.product.eam.service.bm.impl;

import com.alibaba.fastjson.JSON;
import com.binary.core.util.BinaryUtils;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.db.bean.DiagramChangeData;
import com.uinnova.product.eam.model.bm.FlowModelMergeParams;
import com.uinnova.product.eam.model.bm.SavePrivateBatchCIContext;
import com.uinnova.product.eam.service.EamCategorySvc;
import com.uinnova.product.eam.service.ICISwitchSvc;
import com.uinnova.product.eam.service.es.IamsESCIPrivateSvc;
import com.uinnova.product.eam.service.fx.GeneralPullSvc;
import com.uinnova.product.eam.service.fx.ProcessCiRltSvc;
import com.uinnova.product.eam.service.impl.IamsCIPrivateSvc;
import com.uinnova.product.eam.service.impl.IamsCIRltDesignSvc;
import com.uinnova.product.eam.service.impl.IamsCIRltPrivateSvc;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.ESCIRltInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.base.SaveBatchCIContext;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程建模对象及关系数据发布/检出业务实现
 * @author ch
 */
@Slf4j
@Service
public class FlowModelCiRltMerge {

    @Resource
    private ICISwitchSvc ciSwitchSvc;
    @Resource
    private IamsCIPrivateSvc ciPrivateSvc;
    @Resource
    private IamsESCIPrivateSvc esCiPrivateSvc;
    @Resource
    private IamsCIRltPrivateSvc rltPrivateSvc;
    @Resource
    private IamsCIRltDesignSvc rltDesignSvc;
    @Resource
    private FlowModelMergePreProcessor preProcessor;
    @Resource
    private GeneralPullSvc generalPullSvc;
    @Resource
    private ProcessCiRltSvc processCiRltSvc;
    @Resource
    private EamCategorySvc eamCategorySvc;

    public void pushCheck(FlowModelMergeParams params) {

    }

    public void push(FlowModelMergeParams params) {
        // 添加处理模型上级逻辑
        List<ESCIInfo> ciList = new ArrayList<>();
        if (!BinaryUtils.isEmpty(params.getMergeCiList())) {
            ciList.addAll(params.getMergeCiList());
        }
        if (!BinaryUtils.isEmpty(params.getMergeExpCiList())) {
            ciList.addAll(params.getMergeExpCiList());
        }
        if(BinaryUtils.isEmpty(ciList)){
            return;
        }
        Set<Long> classIds = new HashSet<>();
        for (ESCIInfo each : ciList) {
            each.setId(null);
            classIds.add(each.getClassId());
        }
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        //根据业务主键去重
        Map<String, ESCIInfo> ciMap = ciList.stream().collect(Collectors.toMap(CcCi::getCiPrimaryKey, each -> each, (k1, k2) -> k2));
        List<ESCIInfo> saveList = Lists.newArrayList(ciMap.values());
        Map<String, ? extends SaveBatchCIContext> processCtxList = ciSwitchSvc.saveOrUpdateBatchCI(saveList, new ArrayList<>(classIds), params.getOwnerCode(), loginCode, LibType.DESIGN);
        Set<String> changeCodes = new HashSet<>();
        for (SaveBatchCIContext each : processCtxList.values()) {
            if(!each.isChange() && !each.isAdd()){
                continue;
            }
            changeCodes.add(each.getCiCode());
        }
        if(!BinaryUtils.isEmpty(changeCodes)){
            esCiPrivateSvc.increaseCiPublicVersionByCiCodes(Lists.newArrayList(changeCodes), params.getOwnerCode());
        }
        if(BinaryUtils.isEmpty(params.getMergeRltList())) {
            return;
        }
        List<ESCIRltInfo> bindList = new ArrayList<>();
        List<String> distinct = new ArrayList<>();
        for (ESCIRltInfo each : params.getMergeRltList()) {
            if(distinct.contains(each.getUniqueCode())){
                continue;
            }
            distinct.add(each.getUniqueCode());
            each.setId(null);
            bindList.add(each);
        }
        rltDesignSvc.bindBatchCiRlt(bindList, params.getOwnerCode());
    }

    public void pullCheck(Long dirId) {
        // 校验本地冲突数据
        log.info("########### check ci primarykey ###########");
        EamCategory designDirInfo = eamCategorySvc.getById(dirId, LibType.DESIGN);
        Long modelId = designDirInfo.getModelId();
        List<EamCategory> eamCategories = eamCategorySvc.selectByModelId(modelId, LibType.DESIGN, null);
        List<String> diagramIds = new ArrayList<>();
        for (EamCategory eamCategory : eamCategories) {
            if (!BinaryUtils.isEmpty(eamCategory.getDiagramId())) {
                diagramIds.add(eamCategory.getDiagramId());
            }
        }
        List<DiagramChangeData> diagramChangeData = generalPullSvc.pullCheck(diagramIds);
        List<String> primaryKeyList = new ArrayList<>();
        for (DiagramChangeData changeData : diagramChangeData) {
            primaryKeyList.add(changeData.getDesginCiInfo().getCi().getCiPrimaryKey());
        }
        if (CollectionUtils.isEmpty(primaryKeyList)) {
            log.info("############无主键冲突数据");
            return;
        }
        log.info("############存在主键冲突数据primaryKeyList：【{}】", JSON.toJSONString(primaryKeyList));
        processCiRltSvc.freshBindingEleByDEnergyId(primaryKeyList, Env.GENERAL_DIAGRAM_CHECK_OUT);
    }

    public void pull(FlowModelMergeParams params) {
        List<ESCIInfo> ciList = params.getMergeCiList();
        if(BinaryUtils.isEmpty(ciList)){
            return;
        }
        Set<Long> classIds = new HashSet<>();
        for (ESCIInfo each : ciList) {
            each.setId(null);
            each.setOwnerCode(params.getOwnerCode());
            classIds.add(each.getClassId());
        }
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        Map<String, SavePrivateBatchCIContext> contextMap = ciPrivateSvc.saveOrUpdateBatchCI(ciList, new ArrayList<>(classIds), params.getOwnerCode(), loginCode);
        List<Long> ids = contextMap.values().stream().map(SavePrivateBatchCIContext::getEsCi).map(ESCIInfo::getId).distinct().collect(Collectors.toList());
        ciPrivateSvc.makeZeroCiLocalVersionByIds(ids);
        List<ESCIRltInfo> mergeRltList = params.getMergeRltList();
        if(BinaryUtils.isEmpty(mergeRltList)) {
            return;
        }
        for (ESCIRltInfo each : mergeRltList) {
            each.setId(null);
            each.setOwnerCode(params.getOwnerCode());
        }
        Map<String, ESCIRltInfo> filterMap = mergeRltList.stream().collect(Collectors.toMap(ESCIRltInfo::getUniqueCode, each -> each, (k1, k2) -> k2));
        rltPrivateSvc.bindBatchCiRlt(Lists.newArrayList(filterMap.values()), loginCode);
        log.info("########### ci and rlt pull is over ###########");
    }
}
